
use std::{process::Command as cmd, error::Error, ops::Add};

pub struct Command {
    inner:cmd,
}

impl Clone for Command {
    fn clone(&self) -> Self {
        let mut c = Self::new();

        let mut args = vec![];
        let mut index = 0;
        for i in self.inner.get_args() {
            index += 1;
            let tag = i.to_str().unwrap();
            if index == 1 &&  tag == "-c" || tag == "/C" {
                continue;
            } 
            args.push(tag);
        }
        
        c = c.args(args);

        c
    }
}


impl Command {
    pub fn new() -> Self {
        let output = {
            let mut res;
            if cfg!(target_os="linux") {
                res = cmd::new("sh");
                res.arg("-c");
            } else if cfg!(target_os="windows"){
                res = cmd::new("cmd");
                res.arg("/C");
            } else {
                panic!("not support!");
            }

            res
        };
        
        Command{
            inner:output
        }
    }

    pub fn exec(mut self,name:&str) -> Self {
        let args = self.inner.get_args();
        let mut strs = Vec::new();
        strs.push(name.to_string());
        for i in args {
            strs.push(i.to_str().unwrap().to_string());
        }

        self.inner.args(strs);

        self
    }

    pub fn arg(mut self,arg:&str) -> Self {
        self.inner.arg(arg.to_string());

        self
    }

    pub fn args<'a,I>(mut self, args: I) -> Self
    where
        I: IntoIterator<Item = &'a str>,
    {
        let mut str = String::new();
        for arg in args {
            str = str.add(arg);
            str.push(' ');
        }

        self.inner.arg(str);

        self
    }


    pub fn run(&mut self) -> Result<String,Box<dyn Error>> {
        let ret = self.inner.output()?;
        let str = String::from_utf8(ret.stdout)?;
        Ok(str)
    }
}


#[cfg(test)]
mod test{
    use super::Command;

    #[test]
    fn test() {
        let cc = Command::new();
        match cc.exec("ls").args(["-l"]).run() {
            Ok(str) => {println!("result is :{}",str)},
            Err(e) => {println!("err is :{}",e.to_string())},
        }
    }
}